// cf-238c
// 题意：给定一棵n个节点的树，树的没条边是有向边，现在初始你可以控制两个
//       节点，只要是一个节点被控制，从这个节点出去的节点都算被控制。
//       问最少改几条边的方向可以把所有节点都控制。
//
// 题解：首先有一个O(n^2)的算法。
//       我们先简化一下题目，加入说只能控制一个点，那么其实就是从这个点
//       出发做树形dp（或者说做一遍dfs），所有边方向只能是从这个点到所有
//       点形成一颗外向树。现在可以放两个点，我们可以先枚举其中一个点u，
//       另一个点v肯定是在这个点的某一个子树中。造成的影响只有这两个点
//       u-v之间的路径，其他的还是按枚举点u形成的外向树。
//       要进行修改的量就是单独枚举点u产生的sum, 要减去v->u的边加上u->v
//       的边。这样只需要不断维护从根u到每个点的(v->u的边数 - u->v的边数)
//       的最大值。要注意的是这个值要保持始终大于等于零。因为为零时，
//       如果有一条u->v的边按理应该减1, 但是事实上，这条边肯定可以被u
//       控制到，如果-1后sum-(-1)会导致结果费用增加，不符合贪心的原理。
//       可以形象理解为增加点v只是将u-v路径上“靠近”v的点由v控制，这样
//       可能会减少总费用。
//
//       评论区的大神还说了有O(n*m)的做法，m是初始的控制点数。
//       http://codeforces.com/blog/entry/5765?#comment-110988
//
// run: $exec < input
#include <iostream>

int const maxn = 3007;
int head[maxn], end_point[maxn * 2], next[maxn * 2];
bool rev[maxn * 2];
int alloc = 2;
int n, sum, tr;

void add_edge(int u, int v)
{
	end_point[alloc] = v; rev[alloc] = false;
	next[alloc] = head[u]; head[u] = alloc++;

	end_point[alloc] = u; rev[alloc] =  true;
	next[alloc] = head[v]; head[v] = alloc++;
}

void dfs(int u, int parent, int c)
{
	tr = std::max(tr, c);
	for (int p = head[u]; p; p = next[p]) {
		int v = end_point[p];
		if (v == parent) continue;
		sum += rev[p];
		dfs(v, u, std::max(0, c + 2 * rev[p] - 1));
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin >> n;
	for (int i = 1, x, y; i < n; i++) {
		std::cin >> x >> y;
		add_edge(x, y);
	}

	int ans = n;
	for (int i = 1; i <= n; i++) {
		sum = 0; tr = 0;
		dfs(i, 0, 0);
		ans = std::min(ans, sum - tr);
	}
	std::cout << ans << '\n';
}

